MapStruct হল একটি Java টুল যা ডেটা ট্রান্সফরমেশন (যেমন Entity থেকে DTO (Data Transfer Object) তে ম্যাপিং) করার জন্য ব্যবহৃত হয়। এটি কোড জেনারেট করে এবং compile-time এ ম্যাপিং সম্পন্ন করে, ফলে রানটাইমে কোনো অতিরিক্ত পারফরম্যান্স ওভারহেড থাকে না। MapStruct সাধারণত Entity ক্লাস এবং DTO ক্লাসের মধ্যে ডেটা ম্যানিপুলেশন করতে ব্যবহৃত হয়, যা সাধারণত RESTful API তে ব্যবহৃত হয়।
এখানে DTO এবং Entity এর মধ্যে MapStruct ব্যবহার করে কিভাবে ম্যাপিং করা যায় তা বিস্তারিতভাবে আলোচনা করা হবে।
১. DTO এবং Entity কি?
- Entity: Entity ক্লাস সাধারণত ডাটাবেস টেবিলের সাথে সম্পর্কিত হয়। এটি ডেটাবেস থেকে তথ্য সংগ্রহ করতে ব্যবহৃত হয় এবং সাধারণত JPA বা Hibernate এর মাধ্যমে তৈরি হয়।
- DTO (Data Transfer Object): DTO হল একটি অবজেক্ট যা একটি সিস্টেম থেকে আরেকটি সিস্টেমে ডেটা পাঠানোর জন্য ব্যবহৃত হয়। এটি সাধারণত ক্লায়েন্ট-সার্ভার কমিউনিকেশন এর জন্য ব্যবহৃত হয়, যেমন JSON ফরম্যাটে API রেসপন্স।
২. MapStruct এর সাহায্যে Entity থেকে DTO তে Mapping
ধরা যাক, আপনার একটি PersonEntity এবং একটি PersonDTO ক্লাস রয়েছে। আমরা MapStruct ব্যবহার করে Entity থেকে DTO তে ডেটা ম্যাপ করতে চাই।
২.১ Entity Class (PersonEntity)
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class PersonEntity {
@Id
private Long id;
private String firstName;
private String lastName;
private int age;
// Getters and Setters
}
এখানে, PersonEntity একটি ডাটাবেস entity ক্লাস যা JPA এর মাধ্যমে ডাটাবেস টেবিলের সাথে সম্পর্কিত।
২.২ DTO Class (PersonDTO)
public class PersonDTO {
private String fullName;
private int age;
// Getters and Setters
}
এখানে, PersonDTO একটি DTO ক্লাস যা PersonEntity এর ডেটা ধারণ করবে এবং API এর মাধ্যমে ক্লায়েন্টকে পাঠানো হবে।
২.৩ Mapper Interface (PersonMapper)
এখন, MapStruct এর মাধ্যমে PersonEntity থেকে PersonDTO তে ডেটা ম্যাপ করতে একটি Mapper Interface তৈরি করতে হবে।
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
@Mapper
public interface PersonMapper {
PersonMapper INSTANCE = Mappers.getMapper(PersonMapper.class);
PersonDTO personEntityToPersonDTO(PersonEntity personEntity);
}
এখানে, PersonMapper একটি MapStruct Mapper Interface যা personEntityToPersonDTO মেথডের মাধ্যমে PersonEntity থেকে PersonDTO তে ডেটা ম্যাপ করবে। Mappers.getMapper ব্যবহার করে আমরা Mapper Interface এর একটি ইনস্ট্যান্স তৈরি করেছি, যা MapStruct নিজে কোড জেনারেট করবে।
৩. MapStruct Mapper এর ব্যবহারের উদাহরণ
এখন, MapStruct ব্যবহার করে PersonEntity অবজেক্ট থেকে PersonDTO তে ডেটা কিভাবে ম্যাপ করা যায় তা দেখাবো।
৩.১ Main Class (Usage Example)
public class Main {
public static void main(String[] args) {
// Creating PersonEntity instance
PersonEntity personEntity = new PersonEntity();
personEntity.setId(1L);
personEntity.setFirstName("John");
personEntity.setLastName("Doe");
personEntity.setAge(30);
// Using MapStruct to map PersonEntity to PersonDTO
PersonDTO personDTO = PersonMapper.INSTANCE.personEntityToPersonDTO(personEntity);
// Print PersonDTO
System.out.println("Full Name: " + personDTO.getFullName());
System.out.println("Age: " + personDTO.getAge());
}
}
এখানে:
- PersonEntity ইনস্ট্যান্স তৈরি করা হয়েছে এবং তার ডেটা সেট করা হয়েছে।
- PersonMapper.INSTANCE.personEntityToPersonDTO(personEntity) মেথড ব্যবহার করে
PersonEntityথেকেPersonDTOতে ডেটা ম্যাপ করা হয়েছে। - তারপর, PersonDTO এর ডেটা প্রিন্ট করা হয়েছে।
MapStruct কোড জেনারেট করবে যা firstName এবং lastName ফিল্ডগুলিকে একত্রিত করে fullName তৈরি করবে।
৪. Custom Mapping (কাস্টম ম্যাপিং)
MapStruct কাস্টম ম্যাপিং সমর্থন করে, যার মাধ্যমে আপনি ফিল্ডের মধ্যে কাস্টম কনভার্সন লজিক প্রয়োগ করতে পারেন। ধরুন, আপনি চাইছেন যে fullName ফিল্ডে firstName এবং lastName যোগ করা হোক।
৪.১ Custom Mapping Example
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
@Mapper
public interface PersonMapper {
@Mapping(source = "firstName", target = "fullName", expression = "java(personEntity.getFirstName() + \" \" + personEntity.getLastName())")
PersonDTO personEntityToPersonDTO(PersonEntity personEntity);
}
এখানে, @Mapping অ্যানোটেশন ব্যবহার করে firstName এবং lastName কে fullName এ একত্রিত করা হয়েছে।
৫. MapStruct এবং Spring Integration
Spring ফ্রেমওয়ার্কে MapStruct ব্যবহার করা খুবই সহজ। আপনি MapStruct এর Mapper Interface কে Spring Bean হিসাবে কনফিগার করতে পারেন এবং Spring এর ডিপেনডেন্সি ইনজেকশন ব্যবহার করে এটিকে ইনজেক্ট করতে পারেন।
৫.১ Spring Integration Example
@Mapper(componentModel = "spring")
public interface PersonMapper {
PersonDTO personEntityToPersonDTO(PersonEntity personEntity);
}
এখানে, componentModel = "spring" সেট করে আপনি PersonMapper ইন্টারফেসটিকে Spring Bean হিসেবে কনফিগার করেছেন। এর ফলে Spring এর মধ্যে PersonMapper ইনজেক্ট করা যাবে এবং @Autowired এর মাধ্যমে এটি ব্যবহার করা যাবে।
৫.২ Spring Service Example
@Service
public class PersonService {
private final PersonMapper personMapper;
@Autowired
public PersonService(PersonMapper personMapper) {
this.personMapper = personMapper;
}
public PersonDTO convertToDTO(PersonEntity personEntity) {
return personMapper.personEntityToPersonDTO(personEntity);
}
}
এখানে, PersonMapper Spring এর মধ্যে @Autowired ব্যবহার করে ইনজেক্ট করা হয়েছে এবং convertToDTO মেথডের মাধ্যমে PersonEntity থেকে PersonDTO তে ডেটা ট্রান্সফার করা হচ্ছে।
৬. MapStruct এর সুবিধা
- Compile-time Code Generation: MapStruct কম্পাইল টাইমে কোড জেনারেট করে, যা রানটাইম পারফরম্যান্সে কোনো প্রভাব ফেলে না।
- Type Safety: MapStruct টাইপ সেফ ম্যাপিং নিশ্চিত করে, যা ভুল টাইপের ডেটা ম্যাপিং থেকে রক্ষা করে।
- Custom Mapping: আপনি কাস্টম ম্যাপিং কনভার্সন ব্যবহার করতে পারেন, যেমন বিশেষ ক্ষেত্রের জন্য কাস্টম লজিক প্রয়োগ।
- Spring Integration: MapStruct সহজেই Spring ফ্রেমওয়ার্কের সাথে কাজ করে এবং Spring Bean হিসেবে ব্যবহৃত হতে পারে।
- Performance: MapStruct ব্যবহার করলে reflection এর মতো অতিরিক্ত লোড এড়ানো যায়, যা পারফরম্যান্স উন্নত করে।
সারাংশ
MapStruct JavaBeans বা POJOs এর মধ্যে ডেটা ট্রান্সফরমেশন বা ম্যাপিং করতে ব্যবহৃত একটি শক্তিশালী টুল। এটি DTO এবং Entity এর মধ্যে ডেটা ম্যাপ করতে খুবই সহজ, এবং Spring সহ অন্যান্য ফ্রেমওয়ার্কের সাথে ইন্টিগ্রেট করা যায়। MapStruct একটি compile-time কোড জেনারেটর হিসেবে কাজ করে, যার ফলে এটি দ্রুত এবং টাইপ-সেফ ম্যাপিং নিশ্চিত করে। Custom Mapping এবং Spring Integration এর মাধ্যমে আরও কার্যকরী এবং কাস্টম ডেটা ট্রান্সফরমেশন করা সম্ভব।